package net.sansi.v3correctserver.entity.screen;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import net.sansi.v3correctserver.entity.HashEquals;
import net.sansi.v3correctserver.entity.IntPoint;

import java.util.Objects;

/**
 * Created by Fang
 * create time : 2024/11/4
 * IDE : IntelliJ IDEA
 * <p>
 * 矫正区域
 */

@Data
@ApiModel("矫正区域")
public class CorrectArea extends HashEquals {

    public CorrectArea() {}

    public CorrectArea(int areaId, Rect validArea, Rect showArea) {
        this.areaId = areaId;
        this.validArea = validArea;
        this.showArea = showArea;
    }

    public CorrectArea(int areaId, Rect validArea) {
        this.areaId = areaId;
        this.validArea = validArea;
    }

    /**
     * 构建一个没有扩展范围的矫正区域
     *
     * @param areaId 区域id
     * @param width  区域宽度
     * @param height 区域高度
     * @return 矫正区域
     */
    public static CorrectArea buildWithNoExtends(int areaId, int width, int height) {
        return new CorrectArea(areaId,
                new Rect(width, height, new IntPoint(0, 0))
        ).resetShowAreaByExtends(0, new Rect(0, 0, width, height));
    }

    @ApiModelProperty("区域id")
    private Integer areaId;

    public int getAreaId() {
        return areaId;
    }

    @ApiModelProperty("有效区域")
    private Rect validArea;

    @ApiModelProperty("打屏区域（带扩展范围）")
    private Rect showArea;

    /**
     * 重置扩展打屏区域
     *
     * @param extendWith   扩展宽度
     * @param correctRange 扩展范围
     */
    public CorrectArea resetShowAreaByExtends(int extendWith, Rect correctRange) {
        setShowArea(validArea.toExtend(extendWith, extendWith, correctRange));
        return this;
    }

    /**
     * 根据 方向，计算用于计算交集区域的区域
     *
     * @param dir 方向
     * @return 计算区域
     */
    public Rect getUseIntersectRect(int dir) {
        int l = showArea.getLeft(), t = showArea.getTop();
        int r = showArea.getRight(), b = showArea.getBottom();
        if (dir == 0 || dir == 2) {
            l = validArea.getLeft();
            r = validArea.getRight();
        } else {
            t = validArea.getTop();
            b = validArea.getBottom();
        }
        return new Rect(l, t, r - l + 1, b - t + 1);
    }

    /**
     * 遍历区域坐标
     */
    public interface ForeachCallback {
        /**
         * 遍历坐标
         *
         * @param sx 在显示屏中的x坐标
         * @param sy 在显示屏中的y坐标
         * @param rx 在区域 result 中的坐标
         * @param ry 在区域 result 中的坐标
         */
        void callback(int sx, int sy, int rx, int ry);
    }

    /**
     * 遍历有效区域
     *
     * @param iterator 遍历回调
     */
    public void foreachValidArea(ForeachCallback iterator) {
        int l = validArea.getLeft(), t = validArea.getTop();
        validArea.foreach((x, y) -> {
            iterator.callback(x, y, x - l, y - t);
        });
    }

    /**
     * 遍历显示区域
     *
     * @param iterator 遍历回调
     */
    public void foreachShowArea(ForeachCallback iterator) {
        int l = showArea.getLeft(), t = showArea.getTop();
        showArea.foreach((x, y) -> {
            iterator.callback(x, y, x - l, y - t);
        });
    }

    /**
     * 在显示区域中遍历有效区域
     *
     * @param iterator 遍历回调
     */
    public void foreachValidInShowArea(ForeachCallback iterator) {
        int sl = showArea.getLeft(), st = showArea.getTop();
        int vl = validArea.getLeft(), vt = validArea.getTop();
        int ofx = vl - sl, ofy = vt - st;
        validArea.foreach((vx, vy) -> {
            int rx = vx - vl + ofx;
            int ry = vy - vt + ofy;
            iterator.callback(vx, vy, rx, ry);
        });
    }

    @Override
    public boolean equals(Object obj) {
        return super.equals(obj);
    }

    @Override
    public int hashCode() {
        return Objects.hash(areaId, validArea.hashCode(), showArea.hashCode());
    }
}
